/**
* \file		Action.c
* \brief	Code des fonctions du module Action
* \details	C'est ici qu'est le code des accesseurs, mutateurs ainsi que
*		la fonction de test vérifant le bon fonctionnement du module
*		Action et les fonctions définissant les différentes actions.
*/

#include "Action.h"
#include "Terrain.h" /* Nécessaire pour les tests */
#include <string.h>
#include <assert.h>

/*======================== Gestion de la mémoire =======================*/
void initAction(Action *pact)
{
   pact->nomAction = NULL;
   pact->pFAct = NULL;
   pact->representation = NULL;
   pact->actionSuivante = NULL;
}

void creerAction(Action **pnouvAct)
{
   *pnouvAct = (Action *)malloc(sizeof(Action));
   initAction(*pnouvAct);
}

void libereAction(Action *pact)
{
   if(NULL != getNomAction(pact))
	{
	   free(pact->nomAction);
	}

   if(NULL != getRepresentationAction(pact))
	{
	   free(pact->representation);
	}

   pact->pFAct = NULL;
   pact->actionSuivante = NULL;
}

void detruireAction(Action *pact)
{
   libereAction(pact);
   free(pact);
}

/*============================= Accesseurs =============================*/

char *getNomAction(const Action *pact)
{
   return pact->nomAction;
}

/* Renvoie la fonction pointée par pFAct de l'action donnée */
void (*getFonctionAction(const Action *pact)) (Entrepot *, Carte *, int, unsigned int, unsigned int, unsigned int)
{
   return pact->pFAct;
}

char *getRepresentationAction(const Action *pact)
{
   return pact->representation;
}

Action *getActionSuivanteAction(const Action *pact)
{
   return pact->actionSuivante;
}

/*============================== Mutateurs =============================*/

void setNomAction(Action *pact, char *nouvNom)
{
   if(NULL != getNomAction(pact))
	{
	   free(pact->nomAction);
	}
   pact->nomAction = (char *)malloc((1+strlen(nouvNom))*sizeof(char));
   strcpy(pact->nomAction, nouvNom);
}

void setFonctionAction(Action *pact, void (*pnouvFAct)(Entrepot *, Carte *, int, unsigned int, unsigned int, unsigned int))
{
   pact->pFAct = pnouvFAct;
}

void setRepresentationAction(Action *pact, char *nouvRepres)
{
   if(NULL != getRepresentationAction(pact))
	{
	   free(pact->representation);
	}
   pact->representation = (char *)malloc((1+strlen(nouvRepres))*sizeof(char));
   strcpy(pact->representation, nouvRepres);
}

void setActionSuivanteAction(Action *pact, Action *pactSuiv)
{
   pact->actionSuivante = pactSuiv;
}

/*===================== Jouer la fonction du champ =====================*/

void executeFonctionAction(Action *pact, Entrepot *pstock, Carte *pcarte, int modif, unsigned int x, unsigned int y, unsigned int z)
{
   pact->pFAct(pstock, pcarte, modif, x, y, z);
}


/*============================ Les fonctions ============================*/

void inactif(Entrepot *pstock, Carte *pcarte, int modif, unsigned int x, unsigned int y, unsigned int z)
{

}

void recolteBois(Entrepot *pstock, Carte *pcarte, int modif, unsigned int x, unsigned int y, unsigned int z)
{

}

void finRecolteBois(Entrepot *pstock, Carte *pcarte, int modif, unsigned int x, unsigned int y, unsigned int z)
{
   if(100 == getPourcentageProdCaseCarte(pcarte, x, y, z))
	{
	   setNouvProdCaseCarte(pcarte, x, y, z, NULL);
	}

   else
	{
	   ajouteBoisEntr(pstock, modif);
	   ajoutePourcentageProdCaseCarte(pcarte, x, y, z, modif);
	}
}

void recolteMetal(Entrepot *pstock, Carte *pcarte, int modif, unsigned int x, unsigned int y, unsigned int z)
{

}

void finRecolteMetal(Entrepot *pstock, Carte *pcarte, int modif, unsigned int x, unsigned int y, unsigned int z)
{
   if(100 == getPourcentageProdCaseCarte(pcarte, x, y, z))
	{
	   setNouvProdCaseCarte(pcarte, x, y, z, NULL);
	}

   else
	{
	   ajouteMetalEntr(pstock, modif);
	   ajoutePourcentageProdCaseCarte(pcarte, x, y, z, modif);
	}
}


/*========================== Fonctions autres ==========================*/

Action *creerCompleteAction(char *nom, char *repres, void (*pFAct)(Entrepot *, Carte *, int, unsigned int, unsigned int, unsigned int))
{
   Action *pnouvAct;
   creerAction(&pnouvAct);

   setNomAction(pnouvAct, nom);
   setRepresentationAction(pnouvAct, repres);
   setFonctionAction(pnouvAct, pFAct);

   return pnouvAct;
}


/*========================== Fonction de Test ==========================*/

void testAction()
{
   Action *paction;
   Action *paction2;
   char nom[][50] = {"Bartholomeus", "ActionMet", "Nom très très long et imbuvable"};
   int i;
   Entrepot *pstock;
   Carte *pcarte;
   char *fichierDat = {"DatTerr"};
   TabTerrains tableauTerr;

   tableauTerr = creerTabTerrains(fichierDat);
   creerEntr(&pstock);
   pcarte = genererCarte(30,30,3,6,8,7,8,&tableauTerr);


   printf("Test d'Action\n");
   printf("\tCréation et initialisation d'une Action\t\t");
   creerAction(&paction);
   assert(NULL == getNomAction(paction));
   assert(NULL == getFonctionAction(paction));
   assert(NULL == getRepresentationAction(paction));
   printf("OK\n");

   printf("\tAffectation et récupération de valeurs\t\t");
   for(i=0; i<3; i++)
	{
	   setNomAction(paction, nom[i]);
	   assert(0 == strcmp(nom[i], getNomAction(paction)));

	   setRepresentationAction(paction, nom[i]);
	   assert(0 == strcmp(nom[i], getRepresentationAction(paction)));
	}


   printf("OK\n");

   printf("\tCréation d'une Action à partir de données\n");
   paction2 = creerCompleteAction(nom[1], nom[2], finRecolteBois);
   printf("\t\tNom de l'action : %s\n", getNomAction(paction2));
   printf("\t\tReprésentation de l'action : %s\n", getRepresentationAction(paction2));
   printf("\t\tRésultat de l'exécution de la fonction :\n");
   printf("\t\t\tvaleur de bois avant exécution : %u\n", getBoisEntr(pstock));
   executeFonctionAction(paction2, pstock, pcarte, 100000, 1, 1, 1);
   printf("\t\t\tvaleur de bois après exécution : %u\n", getBoisEntr(pstock));

   printf("\tAffectations et exécution de la fonction\tOK\n");
   printf("\n");

   detruireCarte(pcarte);
   detruireEntr(pstock);
   detruireTabTerrains(&tableauTerr);
   detruireAction(paction);
   detruireAction(paction2);
}

